package com.example.springboot3demo.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.boot.convert.ApplicationConversionService;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.converter.Converter;

import java.beans.PropertyDescriptor;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.Map;

public class ObjectConverter {

    // 优先使用的转换服务
    private static final ConversionService conversionService = createConversionService();
    // JSON转换工具
    private static final ObjectMapper objectMapper = new ObjectMapper();

    // 初始化转换服务，可添加自定义转换器
    private static ConversionService createConversionService() {
        // 使用Spring Boot的ApplicationConversionService，它内置了对JSR-310日期类型的转换支持
        ApplicationConversionService service = new ApplicationConversionService();
        
        // 注册自定义的 DateConverter
        service.addConverter(new Converter<String, Date>() {
            @Override
            public Date convert(String source) {
                if (source == null || source.isEmpty()) {
                    return null;
                }
                try {
                    // 尝试多种日期格式
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    return sdf.parse(source);
                } catch (Exception e) {
                    try {
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                        return sdf.parse(source);
                    } catch (Exception ex) {
                        throw new IllegalArgumentException("无法解析日期字符串: " + source, ex);
                    }
                }
            }
        });
        
        return service;
    }

    /**
     * 转换逻辑：
     * 1. 优先使用ConversionService尝试转换
     * 2. 若转换失败，再按原逻辑处理（对象复制、Map转对象、JSON转对象等）
     */
    public static Object convert(Object source, Class<?> targetType) throws Exception {
        // 源对象为null，直接返回null
        if (source == null) {
            return null;
        }

        // 步骤1：优先尝试用ConversionService转换
        if (conversionService.canConvert(source.getClass(), targetType)) {
            return conversionService.convert(source, targetType);
        }

        // 步骤2：处理JSON字符串（ConversionService不支持，单独处理）
        if (source instanceof String) {
            String sourceStr = (String) source;
            if (isJsonString(sourceStr)) {
                return objectMapper.readValue(sourceStr, targetType);
            }
        }

        // 步骤3：源类型与目标类型一致，直接返回
        if (targetType.isInstance(source)) {
            return source;
        }

        // 步骤4：创建目标对象实例
        Object target = targetType.getDeclaredConstructor().newInstance();

        // 步骤5：Map转对象
        if (source instanceof Map) {
            BeanWrapper targetWrapper = new BeanWrapperImpl(target);
            targetWrapper.setConversionService(conversionService);
            targetWrapper.setPropertyValues((Map<?, ?>) source);
        }
        // 步骤6：普通对象转对象（属性复制）
        else {
            BeanWrapper sourceWrapper = new BeanWrapperImpl(source);
            BeanWrapper targetWrapper = new BeanWrapperImpl(target);
            targetWrapper.setConversionService(conversionService);

            for (PropertyDescriptor pd : sourceWrapper.getPropertyDescriptors()) {
                String propertyName = pd.getName();
                if ("class".equals(propertyName)) {
                    continue;
                }

                if (targetWrapper.isWritableProperty(propertyName)) {
                    Object value = sourceWrapper.getPropertyValue(propertyName);
                    // 对属性值也优先使用ConversionService转换
                    Object convertedValue = conversionService.canConvert(value.getClass(), pd.getPropertyType())
                            ? conversionService.convert(value, pd.getPropertyType())
                            : value;
                    targetWrapper.setPropertyValue(propertyName, convertedValue);
                }
            }
        }

        return target;
    }

    // 简单判断是否为JSON字符串
    private static boolean isJsonString(String str) {
        String trimmed = str.trim();
        return (trimmed.startsWith("{") && trimmed.endsWith("}"))
                || (trimmed.startsWith("[") && trimmed.endsWith("]"));
    }


    public static void main(String[] args) throws Exception {
        String a = "2099-05-09";
        System.out.println(convert(a, Date.class));
        System.out.println(convert(a, LocalDate.class));
        System.out.println(convert(a, String.class));
        System.out.println(convert(a, Integer.class));
    }

}